<template>
  <div class="flex h-full flex-col">
    <!-- 搜索和筛选区域 -->
    <div class="mb-4 flex justify-between">
      <el-form :model="searchForm" inline label-width="80px">
        <el-form-item label="角色名称">
          <el-input v-model="searchForm.name" placeholder="请输入角色名称" clearable class="w-48" />
        </el-form-item>
        <el-form-item label="角色编码">
          <el-input v-model="searchForm.code" placeholder="请输入角色编码" clearable class="w-48" />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="searchForm.status" placeholder="请选择状态" clearable class="w-32">
            <el-option label="启用" :value="1" />
            <el-option label="禁用" :value="0" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
        </el-form-item>
      </el-form>
      <el-button type="primary" @click="handleCreateRole" :icon="Plus"> 新增角色 </el-button>
    </div>

    <!-- 角色列表 -->
    <div class="flex h-0 grow flex-col">
      <el-table
        class="grow"
        v-loading="loading"
        :data="roleList.list"
        border
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" />
        <el-table-column prop="id" label="角色ID" width="80" />
        <el-table-column prop="name" label="角色名称" />
        <el-table-column prop="code" label="角色编码" />
        <el-table-column prop="sort" label="排序" width="80" />
        <el-table-column prop="status" label="状态" width="100">
          <template #default="scope">
            <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
              {{ scope.row.status === 1 ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="remark" label="备注" show-overflow-tooltip />
        <el-table-column prop="createdAt" label="创建时间" width="180" show-overflow-tooltip />
        <el-table-column label="操作" width="280" fixed="right">
          <template #default="scope">
            <el-button type="primary" link @click="handleEditRole(scope.row)"> 编辑 </el-button>
            <el-button type="primary" link @click="handleAssignPermission(scope.row)">
              分配权限
            </el-button>
            <el-button type="danger" link @click="handleDeleteRole(scope.row)"> 删除 </el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="mt-2 flex justify-end">
        <el-pagination
          v-model:current-page="searchForm.page"
          v-model:page-size="searchForm.pageSize"
          :page-sizes="[10, 20, 50, 100]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="roleList.total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </div>

    <!-- 权限分配对话框 -->
    <el-dialog v-model="permissionDialogVisible" title="分配资源权限" width="60%" destroy-on-close>
      <div v-loading="loadingPermission">
        <div class="max-h-[60vh] overflow-y-auto">
          <div class="mb-4 rounded-lg bg-gray-50 p-4">
            <p class="mb-2"><strong>角色名称：</strong>{{ selectedRole?.name }}</p>
            <p class="mb-2"><strong>角色编码：</strong>{{ selectedRole?.code }}</p>
            <p class="mb-0"><strong>备注：</strong>{{ selectedRole?.remark || '无' }}</p>
          </div>
          <!-- 权限树 -->
          <el-tree
            :data="permissionTree"
            show-checkbox
            node-key="id"
            ref="permissionTreeRef"
            highlight-current
            :default-expanded-keys="expandedKeys"
            :default-checked-keys="checkedKeys"
            :props="defaultProps"
          />
        </div>
      </div>

      <template #footer>
        <div class="flex justify-end space-x-2">
          <el-button @click="permissionDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmAssignPermission" :loading="loadingAssign">
            确认分配
          </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 角色表单对话框 -->
    <el-dialog v-model="roleDialogVisible" :title="dialogTitle" width="500px" destroy-on-close>
      <el-form ref="roleFormRef" :model="roleForm" label-width="100px" :rules="roleFormRules">
        <el-form-item label="角色名称" prop="name">
          <el-input v-model="roleForm.name" placeholder="请输入角色名称" />
        </el-form-item>
        <el-form-item label="角色编码" prop="code">
          <el-input
            v-model="roleForm.code"
            placeholder="请输入角色编码（如：admin、editor）"
            :disabled="isEditMode"
          />
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input-number controls-position="right" v-model="roleForm.sort" :min="0" :max="9999" />
        </el-form-item>
        <el-form-item label="状态">
          <el-radio-group v-model="roleForm.status">
            <el-radio :label="1">启用</el-radio>
            <el-radio :label="0">禁用</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="roleForm.remark" type="textarea" placeholder="请输入备注" :rows="3" />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="flex justify-end space-x-2">
          <el-button @click="roleDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmRoleForm" :loading="submitting">
            确认
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { getResourceTree } from '@/api/system/resource.api'
import {
  assignResources,
  createRole,
  deleteRole,
  getRoleList,
  getRoleResources,
  updateRole
} from '@/api/system/role.api'
import { to } from '@/utils/promise'
import { Plus } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox, type FormInstance } from 'element-plus'
import { computed, onMounted, reactive, ref } from 'vue'

// 搜索表单
const searchForm = reactive<RoleQueryParams>({
  name: '',
  code: '',
  status: undefined,
  page: 1,
  pageSize: 10
})

// 角色列表
const roleList = ref<PageResponse<RoleFormData>>({
  list: [],
  total: 0,
  page: 1,
  pageSize: 10
})

// 加载状态
const loading = ref(false)
const loadingPermission = ref(false)
const loadingAssign = ref(false)

// 选中的角色
const selectedRole = ref<RoleFormData | null>(null)
const selectedRows = ref<RoleFormData[]>([])

// 权限对话框
const permissionDialogVisible = ref(false)
const permissionTree = ref<ResourceFormData[]>([])
const permissionTreeRef = ref()
const defaultProps = {
  children: 'children',
  label: 'name'
}
const expandedKeys = ref<number[]>([])
const checkedKeys = ref<number[]>([])

// 角色表单对话框
const roleDialogVisible = ref(false)
const roleFormRef = ref<FormInstance>()
const submitting = ref(false)
const currentRole = ref<RoleFormData | null>(null)
const isEditMode = computed(() => !!currentRole.value)
const dialogTitle = computed(() => (isEditMode.value ? '编辑角色' : '新增角色'))

// 角色表单
const roleForm = reactive<RoleFormData>({
  name: '',
  code: '',
  sort: 0,
  status: 1,
  remark: ''
})

// 表单验证规则
const roleFormRules = {
  name: [
    { required: true, message: '请输入角色名称', trigger: 'blur' },
    { min: 2, max: 50, message: '角色名称长度在 2 到 50 个字符', trigger: 'blur' }
  ],
  code: [
    { required: true, message: '请输入角色编码', trigger: 'blur' },
    {
      pattern: /^[a-zA-Z][a-zA-Z0-9_]*$/,
      message: '角色编码必须以字母开头，只能包含字母、数字和下划线',
      trigger: 'blur'
    },
    { min: 2, max: 50, message: '角色编码长度在 2 到 50 个字符', trigger: 'blur' }
  ]
}

// 获取角色列表
const fetchRoleList = async () => {
  loading.value = true
  const [error, response] = await to(getRoleList(searchForm))
  if (error) {
    ElMessage.error('获取角色列表失败')
    return
  }
  roleList.value = response || { list: [], total: 0, page: 1, pageSize: 10 }
  loading.value = false
}

// 搜索
const handleSearch = () => {
  searchForm.page = 1
  fetchRoleList()
}

// 重置搜索
const resetSearch = () => {
  searchForm.name = ''
  searchForm.code = ''
  searchForm.status = undefined
  searchForm.page = 1
  fetchRoleList()
}

// 分页变化
const handleSizeChange = (size: number) => {
  searchForm.pageSize = size
  fetchRoleList()
}

const handleCurrentChange = (current: number) => {
  searchForm.page = current
  fetchRoleList()
}

// 选择变化
const handleSelectionChange = (rows: RoleFormData[]) => {
  selectedRows.value = rows
}

// 处理创建角色
const handleCreateRole = () => {
  currentRole.value = null
  // 重置表单
  Object.assign(roleForm, {
    name: '',
    code: '',
    sort: 0,
    status: 1,
    remark: ''
  })
  roleDialogVisible.value = true
}

// 处理编辑角色
const handleEditRole = (role: RoleFormData) => {
  currentRole.value = role
  // 填充表单数据
  Object.assign(roleForm, {
    name: role.name,
    code: role.code,
    sort: role.sort || 0,
    status: role.status,
    remark: role.remark || ''
  })
  roleDialogVisible.value = true
}

// 确认角色表单提交
const confirmRoleForm = async () => {
  if (!roleFormRef.value) return

  submitting.value = true
  try {
    const [validateError] = await to(roleFormRef.value.validate())
    if (validateError) {
      // 表单验证失败
      return
    }

    if (isEditMode.value && currentRole.value) {
      // 更新角色
      const updateData: RoleUpdateRequest = {
        name: roleForm.name,
        sort: roleForm.sort,
        status: roleForm.status,
        remark: roleForm.remark
      }
      const [updateError] = await to(updateRole(currentRole.value.id!, updateData))
      if (updateError) {
        ElMessage.error('操作失败，请重试')
        return
      }
    } else {
      // 创建角色
      const createData: RoleCreateRequest = {
        name: roleForm.name,
        code: roleForm.code,
        sort: roleForm.sort,
        status: roleForm.status,
        remark: roleForm.remark
      }
      const [createError] = await to(createRole(createData))
      if (createError) {
        ElMessage.error('操作失败，请重试')
        return
      }
    }

    roleDialogVisible.value = false
    // 刷新角色列表
    fetchRoleList()
  } catch (error: any) {
    console.error('角色操作失败:', error)
    ElMessage.error('操作失败，请重试')
  } finally {
    submitting.value = false
  }
}

// 处理删除角色
const handleDeleteRole = async (role: RoleFormData) => {
  const [confirmError] = await to(
    ElMessageBox.confirm(`确定要删除角色"${role.name}"吗？删除后将无法恢复！`, '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
  )
  if (confirmError) {
    ElMessage.error('取消删除')
    return
  }
  const [deleteError] = await to(deleteRole(role.id!))
  if (deleteError) {
    ElMessage.error('删除失败，请重试')
    return
  }
  ElMessage.success('删除成功')
  // 刷新列表
  fetchRoleList()
}

// 分配权限
const handleAssignPermission = async (role: RoleFormData) => {
  selectedRole.value = role

  // 先加载权限树，再加载角色权限
  await loadPermissionTree()
  await loadRoleResources(role.id!)
  permissionDialogVisible.value = true
}

// 加载权限树
const loadPermissionTree = async () => {
  loadingPermission.value = true
  const [error, response] = await to(getResourceTree())
  if (error) {
    ElMessage.error('获取资源树失败')
    return
  }
  permissionTree.value = response || []
  // 默认展开所有节点
  expandedKeys.value = getAllNodeIds(permissionTree.value)
  loadingPermission.value = false
}

// 获取所有节点ID（用于展开）
const getAllNodeIds = (nodes: ResourceFormData[]): number[] => {
  const ids: number[] = []
  const traverse = (node: ResourceFormData) => {
    if (node.id) {
      ids.push(node.id)
    }
    if (node.children && node.children.length > 0) {
      node.children.forEach(traverse)
    }
  }
  nodes.forEach(traverse)
  return ids
}

// 加载角色资源
const loadRoleResources = async (roleId: number) => {
  const [error, response] = await to(getRoleResources(roleId))
  if (error) {
    ElMessage.error('获取角色权限失败')
    return
  }
  checkedKeys.value = filterLeafNodes(response || [])
}

// 过滤出叶子节点（没有子节点的节点）
const filterLeafNodes = (nodeIds: number[]): number[] => {
  const allNodeIds = new Set(nodeIds)
  const leafNodes: number[] = []

  // 遍历权限树，找出所有叶子节点
  const findLeafNodes = (nodes: ResourceFormData[]) => {
    for (const node of nodes) {
      if (node.id && allNodeIds.has(node.id)) {
        // 如果没有子节点，或者所有子节点都不在选中列表中，则认为是叶子节点
        if (!node.children || node.children.length === 0) {
          leafNodes.push(node.id)
        } else {
          // 检查是否有子节点被选中
          const hasSelectedChildren = node.children.some(
            (child) => child.id && allNodeIds.has(child.id)
          )
          if (!hasSelectedChildren) {
            // 如果没有子节点被选中，则当前节点作为叶子节点
            leafNodes.push(node.id)
          }
        }
      }
      // 递归处理子节点
      if (node.children && node.children.length > 0) {
        findLeafNodes(node.children)
      }
    }
  }

  findLeafNodes(permissionTree.value)
  return leafNodes
}

// 确认分配权限
const confirmAssignPermission = async () => {
  if (!selectedRole.value) return

  loadingAssign.value = true
  // 获取选中的节点和半选节点
  // 在非 check-strictly 模式下，半选节点代表部分子节点被选中的父节点
  const checkedNodes = permissionTreeRef.value.getCheckedKeys()
  const halfCheckedNodes = permissionTreeRef.value.getHalfCheckedKeys()

  // 合并所有需要保存的节点ID（包括全选和半选的节点）
  // 这样可以确保父节点也被保存到数据库，避免菜单树构建失败
  const allCheckedIds = [...checkedNodes, ...halfCheckedNodes]

  const [error] = await to(
    assignResources(selectedRole.value.id!, {
      resourceIds: allCheckedIds
    })
  )
  if (error) {
    ElMessage.error('权限分配失败')
    return
  }
  permissionDialogVisible.value = false
  loadingAssign.value = false
}

// 初始化
onMounted(() => {
  fetchRoleList()
})
</script>

<style scoped>
/* 移除了所有自定义样式，改用 Tailwind CSS */
</style>
